package com.jddup.program.comparator.mysql;

import com.jddup.common.pojo.EntityAndDbDifference;
import com.jddup.common.pojo.TableColumn;
import com.jddup.program.comparator.DataTypeCompatibility;
import com.jddup.program.utils.Misc;

import java.util.ArrayList;

/**
 * Created by ZZB on 2017/12/12.
 */
public class MysqlDataTypeCompatibility implements DataTypeCompatibility {
    private static final String ALTER_SQL = "ALTER TABLE `{tableName}` modify COLUMN `{columnName}` TYPE {columnType} ;";

    @Override
    public void compare(EntityAndDbDifference difference, TableColumn entityColumn, TableColumn tableColumn) {
        String tableName = difference.getTableName();
        String entityColumnName = entityColumn.getColumnName();
        String entityColumnType = entityColumn.getColumnType();
        String entityTypeFullName = entityColumn.getTypeFullName();
        String tableColumnType = tableColumn.getColumnType();
        if (entityColumnType.equals("VARCHAR")) {
            if (!tableColumnType.equals("VARCHAR") && !tableColumnType.equals("TEXT") && !tableColumnType.equals("CHAR")
                    && !tableColumnType.equals("TINYTEXT") && !tableColumnType.equals("MEDIUMTEXT")
                    && !tableColumnType.equals("LONGTEXT"))
                notSame(difference, entityColumn, tableColumn);
            else if (Misc.isNotZero(entityColumn.getMaxLength()) && Misc.isNotZero(tableColumn.getMaxLength())
                    && entityColumn.getMaxLength() > tableColumn.getMaxLength()) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段长度为[" + tableColumn.getMaxLength() +
                                "]比实体中约定最大长度[" + entityColumn.getMaxLength() + "]小！请修改实体字段或者执行以下SQL！"),entityColumnName);
            } else if (Misc.isNotZero(entityColumn.getMaxLength()) && Misc.isNotZero(tableColumn.getMaxLength())
                    && entityColumn.getMaxLength() < tableColumn.getMaxLength()) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段长度为[" + tableColumn.getMaxLength() +
                                "]比实体中约定最大长度[" + entityColumn.getMaxLength() +
                                "]大！修改实体字段或者执行以下SQL可以优化数据库性能！"),entityColumnName);
            }
        } else if (entityColumnType.equals("VARBINARY") || entityColumnType.equals("BLOB")) {
            if (!tableColumnType.equals("BINARY") && !tableColumnType.equals("VARBINARY")
                    && !tableColumnType.equals("TINYBLOB") && !tableColumnType.equals("MEDIUMBLOB")
                    && !tableColumnType.equals("LONGBLOB") && !tableColumnType.equals("BLOB"))
                notSame(difference, entityColumn, tableColumn);
            else if (Misc.isNotZero(entityColumn.getMaxLength()) && Misc.isNotZero(tableColumn.getMaxLength())
                    && entityColumn.getMaxLength() > tableColumn.getMaxLength()) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段长度为[" + tableColumn.getMaxLength() +
                                "]比实体中约定最大长度[" + entityColumn.getMaxLength() + "]小！请修改实体字段或者执行以下SQL！"),entityColumnName);
            } else if (Misc.isNotZero(entityColumn.getMaxLength()) && Misc.isNotZero(tableColumn.getMaxLength())
                    && entityColumn.getMaxLength() < tableColumn.getMaxLength()) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段长度为[" + tableColumn.getMaxLength() +
                                "]比实体中约定最大长度[" + entityColumn.getMaxLength() +
                                "]大！修改实体字段或者执行以下SQL可以优化数据库性能！"),entityColumnName);
            }
        } else if (entityColumnType.equals("INT")) {
            if (!tableColumnType.equals("TINYINT") && !tableColumnType.equals("INT") && !tableColumnType.equals("SMALLINT")
                    && !tableColumnType.equals("MEDIUMINT") && !tableColumnType.equals("BIGINT")
                    && !tableColumnType.equals("NUMERIC") && !tableColumnType.equals("FLOAT4") && !tableColumnType.equals("FLOAT8")) {
                notSame(difference, entityColumn, tableColumn);
            } else if (!tableColumnType.equals(entityColumnType)) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段类型[" + tableColumnType +
                                "]和实体中字段类型[" + entityColumnType + "]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);

            }
        } else if (entityColumnType.equals("FLOAT") || entityColumnType.equals("DOUBLE")) {
            if (tableColumnType.equals("FLOAT") || tableColumnType.equals("DOUBLE")) {
                putIntoDifference(difference, getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious, tableName,
                        entityColumnName, "NUMERIC(20,4)", "数据库中[" + entityColumnName + "]使用字段类型为浮点型，可能会丢失进度！请修改实体字段为BigDecimal并执行以下SQL！"), entityColumnName);
            } else {
                putIntoDifference(difference,
                        new EntityAndDbDifference.ModifyDDL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,
                                new ArrayList<>(), "实体中[" + entityColumnName + "]使用字段类型为浮点型，可能会丢失进度！请修改实体字段为BigDecimal"),entityColumnName);
            }
        } else if (entityColumnType.equals("DECIMAL")) {
            if (!tableColumnType.equals("DECIMAL")) {
                notSame(difference, entityColumn, tableColumn);
            } else if (Misc.isNotZero(entityColumn.getPrecision()) && Misc.isNotZero(tableColumn.getPrecision()) &&
                    tableColumn.getPrecision() < entityColumn.getPrecision()) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段类型[" + tableColumn.getTypeFullName() +
                                "]和实体中字段类型[" + entityColumn.getTypeFullName() + "]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            } else if (Misc.isNotZero(entityColumn.getPrecision()) && Misc.isNotZero(tableColumn.getPrecision()) &&
                    tableColumn.getPrecision() > entityColumn.getPrecision()) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段类型[" + tableColumn.getTypeFullName() +
                                "]和实体中字段类型[" + entityColumn.getTypeFullName() + "]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            } else if (Misc.isNotZero(entityColumn.getScale()) && Misc.isNotZero(tableColumn.getScale()) &&
                    tableColumn.getScale() < entityColumn.getScale() ||
                    (Misc.isNotZero(entityColumn.getScale()) && Misc.isZero(tableColumn.getScale()))) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段类型[" + tableColumn.getTypeFullName() +
                                "]和实体中字段类型[" + entityColumn.getTypeFullName() + "]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            } else if ((Misc.isNotZero(entityColumn.getScale()) && Misc.isNotZero(tableColumn.getScale()) &&
                    tableColumn.getScale() > entityColumn.getScale()) ||
                    (Misc.isZero(entityColumn.getScale()) && Misc.isNotZero(tableColumn.getScale()))) {
                putIntoDifference(difference,
                        getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.optimized, tableName, entityColumnName, entityTypeFullName, "数据库中[" + entityColumnName + "]字段类型[" + tableColumn.getTypeFullName() +
                                "]和实体中字段类型[" + entityColumn.getTypeFullName() + "]精度不一致！请修改实体字段或者执行以下SQL！"),entityColumnName);
            }
        } else if (entityColumnType.equals("BIT")) {
            if (!tableColumnType.equals("BIT")
                    && !tableColumn.getTypeFullName().equals("TINYINT(1)")) {
                notSame(difference, entityColumn, tableColumn);
            }
        } else if (entityColumnType.equals("TIMESTAMP")) {
            if (!tableColumnType.equals("TIMESTAMP")
                    && !tableColumnType.equals("DATETIME")
                    ) {
                notSame(difference, entityColumn, tableColumn);
            }
        } else if (!entityColumnType.equals(tableColumnType)) {
            notSame(difference, entityColumn, tableColumn);
        }

    }

    private void notSame(EntityAndDbDifference difference, TableColumn entityColumn, TableColumn dbColumn) {
        String msg = "数据库中字段[" + dbColumn.getColumnName() + " " + dbColumn.getTypeFullName() + "]和实体["
                + entityColumn.getColumnName() + " " + entityColumn.getTypeFullName() + "]不一致！请修改实体字段或者执行以下SQL！";
        EntityAndDbDifference.ModifyDDL modifyDDL = getAlterSQL(EntityAndDbDifference.ModifyDDL.LevelEnums.serious,
                difference.getTableName(), entityColumn.getColumnName(), entityColumn.getTypeFullName(),msg);
        putIntoDifference(difference, modifyDDL,entityColumn.getColumnName());
    }


    @Override
    public String getAlterSQLTemplate(String tableName, String columnName) {
        return ALTER_SQL.replace("{tableName}", tableName)
                .replace("{columnName}", columnName);
    }
}
